package com.ymy.cloud.alibaba.sentinel.exception;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * 全局 {@link BlockExceptionHandler} 降级处理器。
 * 业务方法上不需要添加 {@link SentinelResource}
 * <p>在全局降级处理器处理系统保护规则</p>
 *
 * @author Ringo
 * @date 2021/10/6 14:29
 */
@Component // 注意这里要加入到 IoC 容器
public class BlockExceptionHandlerImpl implements BlockExceptionHandler {

    Logger logger = LoggerFactory.getLogger(BlockExceptionHandlerImpl.class);

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {

        logger.info("BlockExceptionHandle: " + e.getRule());

        // Return 429 (Too Many Requests)
        response.setStatus(429);
        response.setContentType("application/json;charset=UTF-8");

        String tipMsg = "服务器异常, 稍后再试";

        if (e instanceof FlowException) {
            tipMsg = "流控降级";
        } else if (e instanceof DegradeException) {
            tipMsg = "熔断降级";
        } else if (e instanceof SystemBlockException) {
            tipMsg = "系统保护降级";
        }

        Map<String, String> map = new HashMap<>();
        map.put("details", tipMsg);

        PrintWriter out = response.getWriter();
        out.print(new ObjectMapper().writeValueAsString(map));
        out.flush();
        out.close();
    }
}
